/*
 * Copyright 2007-2008  Lukasz Laszko lukaszlaszko@gmail.com
 * 
 * Permission to use, copy, modify, and distribute this software
 * and its documentation for any purpose and without fee is hereby
 * granted, provided that the above copyright notice appear in all
 * copies and that both that the copyright notice and this
 * permission notice and warranty disclaimer appear in supporting
 * documentation, and that the name of the author not be used in
 * advertising or publicity pertaining to distribution of the
 * software without specific, written prior permission.
 * 
 * The author disclaim all warranties with regard to this
 * software, including all implied warranties of merchantability
 * and fitness.  In no event shall the author be liable for any
 * special, indirect or consequential damages or any damages
 * whatsoever resulting from loss of use, data or profits, whether
 * in an action of contract, negligence or other tortious action,
 * arising out of or in connection with the use or performance of
 * this software. 
 */
package org.pg.biomedics.asr.data;

import java.util.*;

import org.pg.biomedics.asr.model.*;

/**
 * Data access object for task manipulation
 * @author Lukasz LAszko
 */
public class TaskManager extends BaseDataManager
{
    // <editor-fold desc="Constructors">
    
    /**
     * Creates a new instance of TaskManager. Data access framework is initailized 
     * according to rules defined in given configuration file
     * @param sqlMapConfig iBatis SQL mapper configuration file
     * @throws org.pg.biomedics.asr.data.DataAccessException
     */
    public TaskManager(String sqlMapConfig) throws DataAccessException
    {
        super(sqlMapConfig);
    }
    
    /**
     * Creates a new instance of TaskManager. Data access framework is initialized 
     * by contructor.
     * @throws org.pg.biomedics.asr.data.DataAccessException
     */
    public TaskManager() throws DataAccessException
    {
        super();
    }   
    
    // </editor-fold>
    
    // <editor-fold desc="Methods">
    
    /**
     * Inserts a new task into database
     * @param task New ASR task
     * @return Saved instance of the task
     * @throws org.pg.biomedics.asr.data.DataAccessException 
     */
    public Task insertTask(Task task) throws DataAccessException
    {
        try
        {
            getSqlMapClient().insert("Tasks.InsertTask", task);
            throwInsertTaskException(task);
            
            return task;
        }
        catch (Exception ex)
        {
            throw new DataAccessException("Can't insert task", ex);
        }
    }
    
    /**
     * Gets list of all tasks stored in database
     * @return tasks extracted from database
     * @throws org.pg.biomedics.asr.data.DataAccessException 
     */
    public Task[] getTasks() throws DataAccessException
    {
        try
        {
            Map parameters = new HashMap();
            getSqlMapClient().queryForList("Tasks.GetTasks", parameters);
            return (Task[])((List)parameters.get("tasks")).toArray(new Task[0]);
        }
        catch (Exception ex)
        {
            throw new DataAccessException("Can't get list of tasks", ex);
        }
    }
    
     /**
     * This method gets task for given task id
     * @param taskId task id
     * @return task
     * @throws org.pg.biomedics.asr.data.DataAccessException 
     */
    public Task getTask(int taskId) throws DataAccessException
    {
        try
        {
            Map parameters = new HashMap();
            parameters.put("taskId", taskId);
            getSqlMapClient().queryForObject("Tasks.GetTaskById", parameters);
            
            List result = (List)parameters.get("task");
            if (result.size() == 0)
                return null;
            else
                return (Task)result.get(0);                
        }
        catch (Exception ex)
        {
            throw new DataAccessException("Can't get task by id", ex);
        }
    }   
    
    /**
     * This method gets task for given unique task id
     * @param taskUniqueId unique task id (GUID)
     * @return task
     * @throws org.pg.biomedics.asr.data.DataAccessException 
     */
    public Task getTask(String taskUniqueId) throws DataAccessException
    {
        try
        {
            Map parameters = new HashMap();
            parameters.put("taskUniqueId", taskUniqueId);
            getSqlMapClient().queryForObject("Tasks.GetTaskByUniqueId", parameters);
            
            List result = (List)parameters.get("task");
            if (result.size() == 0)
                return null;
            else
                return (Task)result.get(0);                
        }
        catch (Exception ex)
        {
            throw new DataAccessException("Can't get task by unique id", ex);
        }
    }    
    
    /**
     * Gets list of tasks currently in given state
     * @param stateCode state code
     * @return list of tasks in the state
     * @throws org.pg.biomedics.asr.data.DataAccessException
     */
    public Task[] getTasks(String stateCode) throws DataAccessException
    {
        try
        {
            Map parameters = new HashMap();
            parameters.put("stateCode", stateCode);
            
            getSqlMapClient().queryForList("Tasks.GetTasksByState", parameters);
            return (Task[])((List)parameters.get("tasks")).toArray(new Task[0]);
        }
        catch (Exception ex)
        {
            throw new DataAccessException(String.format("Can't get list of tasks for state %1", stateCode), ex);
        }
    }
    
    /**
     * Assigns current state to the task
     * @param task ASR task, must exist in datbase
     * @param stateCode new state code 
     * @throws org.pg.biomedics.asr.data.DataAccessException
     */
    public void SetTaskState(Task task, String stateCode) throws DataAccessException
    {
        try
        {
            Map parameters = new HashMap();
            parameters.put("taskId", task.getId());
            parameters.put("stateCode", stateCode);
            
            getSqlMapClient().insert("Tasks.SetTaskState", parameters);
            
            Integer result = (Integer)parameters.get("resultCode");
            throwSetTaskStateException(result.intValue(), task, stateCode);
        }
        catch (Exception ex)
        {
            throw new DataAccessException("Can't set task state", ex);
        }
    }
               
    /**
     * Gets full state history of given task
     * @param task ASR task instance
     * @return list of history entries
     * @throws org.pg.biomedics.asr.data.DataAccessException
     */
    public TaskHistoryEntry[] getTaskHistory(Task task) throws DataAccessException
    {
        try
        {
            Map parameters = new HashMap();
            parameters.put("taskId", task.getId());
                    
            getSqlMapClient().queryForList("Tasks.GetTaskHistory", parameters);
            
            List historyList = (List)parameters.get("history");
            return (TaskHistoryEntry[])historyList.toArray(new TaskHistoryEntry[0]);
        }
        catch (Exception ex)
        {
            throw new DataAccessException("Can't get task history", ex);
        }
    }
    
    // </editor-fold>
    
    // <editor-fold desc="Support methods">
    
    private void throwInsertTaskException(Task task) throws DataAccessException
    {
        switch (task.getId())
        {
            case -1:
                throw new DataAccessException(String.format("Type code %1 doesn't exist", task.getTypeCode()));
            case -2:
                throw new DataAccessException(String.format("Priority code %1 doesn't exist", task.getPriorityCode()));
        }
    }
    
    private void throwSetTaskStateException(int result, Task task, String stateCode) 
            throws DataAccessException
    {
        switch (result)
        {
            case -1:
                throw new DataAccessException(String.format("Task %1 doesn't exist", task.getId()));
            case -2:
                throw new DataAccessException(String.format("State code %1 doesn't exist", stateCode));
        }
    }
    
    // </editor-fold>
}
